<?php

namespace common\service;

use support\Db;
use common\model\TaskModel;
use support\SingletonTrait;
use support\EntityTaskFilterParser;

class ProducerManageHistoryService
{
    // 单例模式工具
    use SingletonTrait;

    use EntityTaskFilterParser;

    /**
     * 制片管理历史任务列表
     * @param $todoStepCategoryIdListFilter
     * @param $projectId
     * @param $userId
     * @param $startTime
     * @param $endTime
     * @param $timeType
     * @param $page
     * @return array
     * @throws \Exception
     */
    public function historyTaskList($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $timeType, $page): array
    {
        $res = [
            'total' => 0,
            'rows' => [],
        ];
        $sql = "";
        switch ($timeType) {
            case 'delivery':
                // 应交付
                $sql = $this->getDeliveryHistoryTaskIds($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $page);
                break;
            case  'done':
                // 应完成
                $sql = $this->getFinalHistoryTaskIds($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $page);
                break;
            case "in_plan_done":
                // 计划内完成
                $sql = $this->getFinalHistoryTaskIds($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $page, true);
                break;
            case "in_plan_delivery":
                // 计划内交付
                $sql = $this->getDeliveryHistoryTaskIds($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $page, true);
                break;
        }
        if (empty($sql)) {
            return $res;
        }
        $total = Db::query('SELECT COUNT(id) as count FROM (' . $sql . ') AS temp_task')[0]['count'];
        if (empty($total)) {
            return $res;
        }
        $data = Db::query($sql . ' limit ' . ($page[1] * ($page[0] - 1)) . ',' . $page[1]);
        if (empty($data)) {
            return $res;
        }
        $ids = array_column($data, 'id');
        if (empty($ids)) {
            return $res;
        }
        $taskFilter = [
            'task.id' => ['IN', $ids]
        ];

        $pageCount = model(TaskModel::class)
            ->join('entity on task.entity_id = entity.id', 'LEFT')
            ->join('module on module.id = entity.module_id', 'LEFT')
            ->where($taskFilter)->count();
        if (empty($pageCount)) {
            return $res;
        }

        $order = $param['order'] ?? 'task.plan_end_time ASC';
        $list = ProducerManageService::getInstance()->getTaskListData($taskFilter, $order, $param['version_only_published'] ?? false);

        return [
            'total' => $total,
            'rows' => $list,
        ];
    }

    /**
     * 制片管理历史交付任务Id
     * @param $todoStepCategoryIdListFilter
     * @param $projectId
     * @param $userId
     * @param $startTime
     * @param $endTime
     * @param bool $actuallyDelivery
     * @return array
     */
    public function getDeliveryHistoryTaskIds($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $page, bool $actuallyDelivery = false)
    {
        // 查询交付
        $taskSql = $this->getTaskDeliveryHistorySql($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $actuallyDelivery);
        // 发布
        $delayOrderTaskSql = $this->getPublishedTaskSql($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $actuallyDelivery);
        return $taskSql . 'union' . $delayOrderTaskSql;
    }

    /**
     * 制片管理历史交付任务Id
     * @param $todoStepCategoryIdListFilter
     * @param $projectId
     * @param $userId
     * @param $startTime
     * @param $endTime
     * @param bool $actuallyDone
     * @return array
     */
    public function getFinalHistoryTaskIds($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $page, bool $actuallyDone = false)
    {
        // 查询交付
        $taskSql = $this->getTaskFinalHistorySql($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $actuallyDone);

        // 发布
        $delayOrderTaskSql = $this->getOrderDelayTaskSql($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, $actuallyDone);
        return $taskSql . 'union' . $delayOrderTaskSql;
    }

    /**
     * 应完成任务
     * @param $todoStepCategoryIdListFilter
     * @param $projectId
     * @param $userId
     * @param $startTime
     * @param $endTime
     * @param bool $actuallyDone
     * @return string
     */
    public function getTaskFinalHistorySql($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, bool $actuallyDone = false)
    {
        $closedStatusId = StatusService::getInstance()->getTaskDefaultClosedStatus()['id'];
        $taskQuery = model(TaskModel::class)->where(["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ['NEQ', $closedStatusId]]);
        if (!empty($todoStepCategoryIdListFilter)) {
            $taskQuery->join("task_relation_tag r_step_category on r_step_category.link_module_code in ('step_category', 'show_step_category') and r_step_category.task_id = task.id")
                ->where(['r_step_category.link_id' => $todoStepCategoryIdListFilter]);
        }
        if (!empty($userId)) {
            $taskQuery->join('task_member on task_member.task_id = task.id')
                ->where(['task_member.partner' => $userId]);
        }
        if (!empty($projectId)) {
            $taskQuery->where(['task.project_id' => $projectId]);
        }
        if (!empty($startTime) && !empty($endTime)) {
            $taskQuery->where(['task.plan_end_time' => ['BETWEEN', [$startTime, $endTime]]]);
            if ($actuallyDone) {
                $taskQuery->where(['task.end_time' => ['BETWEEN', [$startTime, $endTime]]]);
            }
        }
        $taskField = [
            '`task`.`id`'
        ];
        return $taskQuery->field($taskField)->buildSql();
    }

    /**
     * 延期原计划时间
     * @param $todoStepCategoryIdListFilter
     * @param $projectId
     * @param $userId
     * @param $startTime
     * @param $endTime
     * @param bool $actuallyDone
     * @return string
     */
    public function getOrderDelayTaskSql($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, bool $actuallyDone = false)
    {
        $closedStatusId = StatusService::getInstance()->getTaskDefaultClosedStatus()['id'];
        $delayOrderTaskQuery = model(TaskModel::class)->where(["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ['NEQ', $closedStatusId]]);
        $delayOrderTaskQuery->join('delay_order_task dot on task.id = dot.task_id');
        if (!empty($todoStepCategoryIdListFilter)) {
            $delayOrderTaskQuery->join("task_relation_tag r_step_category on r_step_category.link_module_code in ('step_category', 'show_step_category') and r_step_category.task_id = task.id")
                ->where(['r_step_category.link_id' => $todoStepCategoryIdListFilter]);
        }
        if (!empty($startTime) && !empty($endTime)) {
            $delayOrderTaskQuery->where(['dot.original_plan_time' => ['BETWEEN', [$startTime, $endTime]]]);
            if ($actuallyDone) {
                $delayOrderTaskQuery->where(['task.end_time' => ['BETWEEN', [$startTime, $endTime]]]);
            }
        }
        if (!empty($projectId)) {
            $delayOrderTaskQuery->where(['task.project_id' => $projectId]);
        }
        if (!empty($userId)) {
            $delayOrderTaskQuery->join('task_member on task_member.task_id = task.id')
                ->where(['task_member.partner' => $userId]);
        }
        $delayOrderTaskField = [
            '`task`.`id`'
        ];
        return $delayOrderTaskQuery->field($delayOrderTaskField)->group("task.id")->buildSql();
    }

    /**
     * 交付sql
     * @param $todoStepCategoryIdListFilter
     * @param $projectId
     * @param $userId
     * @param $startTime
     * @param $endTime
     * @param bool $actuallyDelivery
     * @return string
     */
    public function getTaskDeliveryHistorySql($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, bool $actuallyDelivery = false)
    {
        $closedStatusId = StatusService::getInstance()->getTaskDefaultClosedStatus()['id'];
        $taskQuery = model(TaskModel::class)->where(['task.step_type' => ['NEQ', TaskModel::STEP_TYPE_STEP_CATEGORY]])->where(["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ['NEQ', $closedStatusId]]);
        if (!empty($todoStepCategoryIdListFilter)) {
            $taskQuery->join("task_relation_tag r_step_category on r_step_category.link_module_code in ('step_category', 'show_step_category') and r_step_category.task_id = task.id")
                ->where(['r_step_category.link_id' => $todoStepCategoryIdListFilter]);
        }
        if (!empty($userId)) {
            $taskQuery->join('task_member on task_member.task_id = task.id')
                ->where(['task_member.partner' => $userId]);
        }
        if (!empty($projectId)) {
            $taskQuery->where(['task.project_id' => $projectId]);
        }
        if (!empty($startTime) && !empty($endTime)) {
            $taskQuery->where(['task.plan_delivery_time' => ['BETWEEN', [$startTime, $endTime]]]);
            if ($actuallyDelivery) {
                $taskQuery->where(['task.delivery_time' => ['BETWEEN', [$startTime, $endTime]]]);
            }
        }
        $taskField = [
            '`task`.`id`'
        ];
        return $taskQuery->field($taskField)->buildSql();
    }

    /**
     * 发布任务sql
     * @param $todoStepCategoryIdListFilter
     * @param $projectId
     * @param $userId
     * @param $startTime
     * @param $endTime
     * @param bool $actuallyDelivery
     * @return string
     */
    public function getPublishedTaskSql($todoStepCategoryIdListFilter, $projectId, $userId, $startTime, $endTime, bool $actuallyDelivery = false)
    {
        $closedStatusId = StatusService::getInstance()->getTaskDefaultClosedStatus()['id'];
        $versionModuleId = module_by_code('version')['id'];
        $delayOrderTaskQuery = model(TaskModel::class)->where(['task.step_type' => ['NEQ', TaskModel::STEP_TYPE_STEP_CATEGORY]])->where(["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))" => ['NEQ', $closedStatusId]]);
        if (!empty($versionModuleId)) {
            $delayOrderTaskQuery->join("version v on task.id = v.link_id and v.module_id = $versionModuleId");
        }
        if (!empty($userId)) {
            $delayOrderTaskQuery->join('task_member on task_member.task_id = task.id')
                ->where(['task_member.partner' => $userId]);
        }
        if (!empty($todoStepCategoryIdListFilter)) {
            $delayOrderTaskQuery->join("task_relation_tag r_step_category on r_step_category.link_module_code in ('step_category', 'show_step_category') and r_step_category.task_id = task.id")
                ->where(['r_step_category.link_id' => $todoStepCategoryIdListFilter]);
        }
        if (!empty($startTime) && !empty($endTime)) {
            $delayOrderTaskQuery->where(['v.published' => ['BETWEEN', [$startTime, $endTime]]]);
            if ($actuallyDelivery) {
                $delayOrderTaskQuery->where(['task.delivery_time' => ['BETWEEN', [$startTime, $endTime]]]);
            }
        }
        if (!empty($projectId)) {
            $delayOrderTaskQuery->where(['task.project_id' => $projectId]);
        }
        $delayOrderTaskField = [
            '`task`.`id`'
        ];
        return $delayOrderTaskQuery->field($delayOrderTaskField)->buildSql();
    }
}